home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 June: Reference Library / Dev.CD Jun 94.toast / Periodicals / develop / develop Issue 10 / develop 10 code / Picture Utilities / sample utilities.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-08  |  7.5 KB  |  302 lines  |  [TEXT/KAHL]

  1. #include <MacHeaders>
  2. #include <PictUtil.h>
  3. #include <Memory.h>
  4. #include <GestaltEqu.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include "sample utilities.h"
  8.  
  9.  
  10. static OSErr CheckForTempMemory(void)
  11. {
  12.     #define hasOurTempMem ((1 << gestaltTempMemSupport) | (1 << gestaltRealTempMemory) | (1 << gestaltTempMemTracked))
  13.     OSErr error;
  14.     long result;
  15.  
  16.     if( error = Gestalt(gestaltOSAttr, &result) )
  17.         return error;
  18.     if( (result & hasOurTempMem) == hasOurTempMem )
  19.         return noErr;
  20.     return memFullErr;
  21.  
  22.     #undef hasOurTempMem
  23. }
  24.  
  25.  
  26. void *GetBuffer(Handle *referencePtr, long *sizePtr, bufferType type)
  27. {
  28.     OSErr error;
  29.     Handle reference = *referencePtr;
  30.     long requestedSize = *sizePtr;
  31.  
  32. /*    if we were passed an old buffer and it is still allocated and it is at least the requested size, then return the old
  33.     buffer handle; otherwise, dispose of the old buffer and try to allocate a new one. */
  34.  
  35.     if( reference ) {
  36.         long oldSize;
  37.         if( *reference && (oldSize = GetHandleSize(reference)) >= requestedSize ) {
  38.             if( type == bufferExactSize && oldSize != requestedSize )
  39.                 SetHandleSize(reference, requestedSize);
  40.             goto returnReference;
  41.         }
  42.         DisposeHandle(reference);
  43.     }
  44.  
  45. /*    try to allocate our requested size first in the multifinder heap, then in the application heap if the multifinder attempt
  46.     fails. if we suceed, then mark the block as purgable, lock it down and return its dereferenced pointer. if we requested
  47.     an exact size and we didn’t get it, then return nil */
  48.  
  49.     if( CheckForTempMemory() != noErr || (reference = TempNewHandle(requestedSize, &error)) == nil )
  50.         reference = NewHandle(requestedSize);
  51.     if( reference )
  52.         goto returnReference;
  53.     else if( type == bufferExactSize ) {
  54.         *referencePtr = nil;
  55.         *sizePtr = nil;
  56.         return nil;
  57.     }
  58.  
  59.     while( reference == nil ) {
  60.         requestedSize = ((requestedSize >> 1) + 3) & 3;
  61.         if( requestedSize == 0 )
  62.             PostError(memFullErr);
  63.         if( CheckForTempMemory() != noErr || (reference = TempNewHandle(requestedSize, &error)) == nil )
  64.             reference = NewHandle(requestedSize);
  65.     }
  66.  
  67. returnReference:
  68.     HPurge(reference);
  69.     HLock(reference);
  70.     *referencePtr = reference;
  71.     *sizePtr = requestedSize;
  72.     return *reference;
  73. }
  74.  
  75.  
  76. void FindScreen(screenType type, short hSize, short vSize, Rect *bounds)
  77. {
  78.     bounds->top = 40;
  79.     bounds->left = 40;
  80.  
  81.     bounds->right = bounds->left + hSize;
  82.     bounds->bottom = bounds->top + vSize;
  83. }
  84.  
  85.  
  86. void PostError(long error)
  87. {
  88.     char errorString[256];
  89.     sprintf(&errorString[1], "an error occurred (%ld).", error);
  90.     errorString[0] = strlen(&errorString[1]);
  91.     DebugStr(errorString);
  92. }
  93.  
  94.  
  95. static pascal void ReadDiskPicture(char *destination, short count)
  96. {
  97.     diskPictureRecord *picture;
  98.     CGrafPtr currentPort;
  99.     OSErr error;
  100.     long bytesLeft;
  101.  
  102.     IfDebug(count == 0, "\pour spool proc should never be called with a count of zero");
  103.  
  104.     GetPort(¤tPort);
  105.     picture = (diskPictureRecord *)((long)currentPort->grafProcs - offsetField(diskPictureRecord, procs));
  106.  
  107.     bytesLeft = picture->bufferStart + picture->bufferSize - picture->bufferPtr;
  108.     while( count ) {
  109.         long bytesRead;
  110.  
  111.         if( count <= bytesLeft ) {
  112.             BlockMove(picture->bufferPtr, destination, (long)count);
  113.             picture->bufferPtr += count;
  114.             return;
  115.         }
  116.  
  117.         BlockMove(picture->bufferPtr, destination, bytesLeft);
  118.         destination += bytesLeft;
  119.         count -= bytesLeft;
  120.         picture->bufferPtr = picture->bufferStart;
  121.         bytesLeft = bytesRead = picture->bufferSize;
  122.         error = FSRead(picture->file, &bytesRead, picture->bufferPtr);
  123.         if( error ) {
  124.             short *tempPtr = (short *)(picture->bufferPtr + bytesRead);
  125.             long counter = picture->bufferSize - bytesRead;
  126.             short fillValue = 0x00FF;
  127.  
  128.             if( (long)tempPtr & 0x1 ) {
  129.                 *(char *)tempPtr = 0;
  130.                 tempPtr = (short *)((char *)tempPtr + 1);
  131.                 --counter;
  132.                 fillValue = 0xFF00;
  133.             }
  134.             counter /= sizeof(short);
  135.             while( --counter >= 0 )
  136.                 *tempPtr++ = fillValue;
  137.         }
  138.     }
  139. }
  140.  
  141.  
  142. void InstallDiskPicture(diskPicture source)
  143. {
  144.     CGrafPtr currentPort;
  145.     OSErr error;
  146.     diskPictureRecord *picture = *source;
  147.  
  148.     if( picture->installedPort )
  149.         PostError(disk_picture_already_installed);
  150.  
  151.     HLock(source);
  152.     GetPort(¤tPort);
  153.  
  154.     {    long fileSize;
  155.         void *cachePtr;
  156.         if( error = GetEOF(picture->file, &fileSize) )
  157.             PostError(error);
  158.         fileSize -= 512;    /* subtract the file header */
  159.         if( cachePtr = GetBuffer((Handle *)&picture->cachedPicture, &fileSize, bufferExactSize) ) {
  160.             if( error = SetFPos(picture->file, fsFromStart, 512) )
  161.                 PostError(error);
  162.             if( error = FSRead(picture->file, &fileSize, cachePtr) )
  163.                 PostError(error);
  164.             picture->installedPort = currentPort;
  165.             return;
  166.         }
  167.     }
  168.  
  169.     picture->bufferSize = 32000;
  170.     picture->bufferStart = GetBuffer(&picture->bufferRef, &picture->bufferSize, bufferCanBeSmaller);
  171.     picture->bufferPtr = picture->bufferStart + picture->bufferSize;
  172.     if( error = SetFPos(picture->file, fsFromStart, 512 + sizeof(Picture)) )
  173.         PostError(error);
  174.  
  175.     picture->installedPort = currentPort;
  176.     picture->savedProcs = currentPort->grafProcs;
  177.     currentPort->grafProcs = &picture->procs;
  178. }
  179.  
  180.  
  181. void RemoveDiskPicture(diskPicture source)
  182. {
  183.     diskPictureRecord *picture = *source;
  184.     if( picture->installedPort == nil )
  185.         PostError(disk_picture_not_installed);
  186.  
  187.     if( picture->cachedPicture ) {
  188.         HUnlock(picture->cachedPicture);
  189.         goto exit;
  190.     }
  191.  
  192.     picture->installedPort->grafProcs = picture->savedProcs;
  193.  
  194.     HUnlock(picture->bufferRef);
  195.     picture->bufferStart = nil;
  196. exit:
  197.     picture->installedPort = nil;
  198.     HUnlock(source);
  199. }
  200.  
  201.  
  202. void GetDiskPictureInfo(diskPicture source, PictInfo *result, short verb, short requestedColors, short method)
  203. {
  204.     diskPictureRecord *picture;
  205.     OSErr error;
  206.  
  207.     InstallDiskPicture(source);
  208.     picture = *source;
  209.     if( error = GetPictInfo(picture->cachedPicture ? picture->cachedPicture : picture->picture, result, verb,
  210.         requestedColors, method, 0) ) {
  211.         PostError(error);
  212.     }
  213.     RemoveDiskPicture(source);
  214. }
  215.  
  216.  
  217. void DrawDiskPicture(diskPicture source)
  218. {
  219.     diskPictureRecord *picture;
  220.  
  221.     InstallDiskPicture(source);
  222.     picture = *source;
  223.     DrawPicture(picture->cachedPicture ? picture->cachedPicture : picture->picture, &picture->bounds);
  224.     RemoveDiskPicture(source);
  225. }
  226.  
  227.  
  228. diskPicture NewDiskPicture(FSSpec *file)
  229. {
  230.     OSErr error;
  231.     long count;
  232.     diskPicture newPicture;
  233.     diskPictureRecord *picture;
  234.  
  235.     newPicture = (diskPicture)NewHandle(sizeof(diskPictureRecord));
  236.     HLock(newPicture);
  237.     picture = *newPicture;
  238.     picture->owners = 1;
  239.     picture->picture = nil;
  240.     picture->file = 0;
  241.     picture->cachedPicture = 0;
  242.     picture->installedPort = 0;
  243.     picture->bufferRef = nil;
  244.  
  245.     if( error = FSpOpenDF(file, fsRdPerm, &picture->file) )
  246.         goto errorExit;
  247.     if( error = SetFPos(picture->file, fsFromStart, 512) )
  248.         goto errorExit;
  249.  
  250.     picture->picture = (PicHandle)NewHandle(sizeof(Picture));
  251.     if( picture->picture == nil || MemError() )
  252.         goto errorExit;
  253.  
  254.     HLock(picture->picture);
  255.     count = sizeof(Picture);
  256.     if( error = FSRead(picture->file, &count, *picture->picture) )
  257.         goto errorExit;
  258.     BlockMove(&(*picture->picture)->picFrame, &picture->bounds, sizeof(Rect));
  259.     HUnlock(picture->picture);
  260.  
  261.     SetStdCProcs(&picture->procs);
  262.     picture->procs.getPicProc = (void *)ReadDiskPicture;
  263.  
  264.     HUnlock(newPicture);
  265.     return newPicture;
  266.  
  267. errorExit:
  268.     PostError(error);
  269.     DisposeDiskPicture(newPicture);
  270.     return nil;
  271. }
  272.  
  273.  
  274. void DisposeDiskPicture(diskPicture target)
  275. {
  276.     diskPictureRecord *picture = *target;
  277.  
  278.     if( picture->owners > 1 ) {
  279.         --picture->owners;
  280.         return;
  281.     }
  282.  
  283.     if( picture->picture )
  284.         DisposeHandle(picture->picture);
  285.     if( picture->file )
  286.         FSClose(picture->file);
  287.     DisposeHandle(target);
  288. }
  289.  
  290.  
  291. diskPicture CloneDiskPicture(diskPicture source)
  292. {
  293.     (*source)->owners += 1;
  294.     return source;
  295. }
  296.  
  297.  
  298. void GetDiskPictureBounds(diskPicture source, Rect *bounds)
  299. {
  300.     BlockMove(&(*source)->bounds, bounds, sizeof(Rect));
  301. }
  302.